/*
 * Copyright (c) 2012 Tomas Shestakov. <http://code.google.com/p/jmmo/>
 */

package jmmo.engine.property

/**
 * Implements [[jmmo.engine.property.Binding]] trait for 1 property
 * form which depended some [[jmmo.engine.property.BoundProperty]]
 * @param f predicate with 1 argument to calculate `Binding` value
 * @param p1 `Property` 1 from which the `Binding` depends
 * @tparam R type of `Binding` value
 * @tparam A `Property` 1 type
 */
class Binding1[R, A](val f: (A) => R, val p1: Property[A]) extends Binding[R] {

  def apply(): R = f(p1())

  def dependencies: Seq[Property[_]] = Seq(p1)
}

/**
 * Implements [[jmmo.engine.property.Binding]] trait for 2 properties
 * form which depended some [[jmmo.engine.property.BoundProperty]]
 * @param f predicate with 1 argument to calculate `Binding` value
 * @param p1 `Property` 1 from which the `Binding` depends
 * @param p2 `Property` 2 from which the `Binding` depends
 * @tparam R type of `Binding` value
 * @tparam A `Property` 1 type
 * @tparam B `Property` 2 type
 */
class Binding2[R, A,B](val f: (A,B) => R, val p1:Property[A],val p2:Property[B]) extends Binding[R] {

  def apply(): R = f(p1(),p2())

  def dependencies: Seq[Property[_]] = Seq(p1,p2)
}

/**
 * Implements [[jmmo.engine.property.Binding]] trait for 3 properties
 * form which depended some [[jmmo.engine.property.BoundProperty]]
 * @param f predicate with 1 argument to calculate `Binding` value
 * @param p1 `Property` 1 from which the `Binding` depends
 * @param p2 `Property` 2 from which the `Binding` depends
 * @param p3 `Property` 3 from which the `Binding` depends
 * @tparam R type of `Binding` value
 * @tparam A `Property` 1 type
 * @tparam B `Property` 2 type
 * @tparam C `Property` 3 type
 */
class Binding3[R, A,B,C](val f: (A,B,C) => R, val p1:Property[A],val p2:Property[B],val p3:Property[C]) extends Binding[R] {

  def apply(): R = f(p1(),p2(),p3())

  def dependencies: Seq[Property[_]] = Seq(p1,p2,p3)
}

/**
 * Implements [[jmmo.engine.property.Binding]] trait for 4 properties
 * form which depended some [[jmmo.engine.property.BoundProperty]]
 */
class Binding4[R, A,B,C,D](val f: (A,B,C,D) => R, val p1:Property[A],val p2:Property[B],val p3:Property[C],
                                                                             val p4:Property[D]) extends Binding[R] {

  def apply(): R = f(p1(),p2(),p3(),p4())

  def dependencies: Seq[Property[_]] = Seq(p1,p2,p3,p4)
}

/**
 * Implements [[jmmo.engine.property.Binding]] trait for 5 properties
 * form which depended some [[jmmo.engine.property.BoundProperty]]
 */
class Binding5[R, A,B,C,D,E](val f: (A,B,C,D,E) => R, val p1:Property[A],val p2:Property[B],val p3:Property[C],
                                                          val p4:Property[D],val p5:Property[E]) extends Binding[R] {

  def apply(): R = f(p1(),p2(),p3(),p4(),p5())

  def dependencies: Seq[Property[_]] = Seq(p1,p2,p3,p4,p5)
}

/**
 * Implements [[jmmo.engine.property.Binding]] trait for 6 properties
 * form which depended some [[jmmo.engine.property.BoundProperty]]
 */
class Binding6[R, A,B,C,D,E,F](val f: (A,B,C,D,E,F) => R, val p1:Property[A],val p2:Property[B],val p3:Property[C],
                                        val p4:Property[D],val p5:Property[E],val p6:Property[F]) extends Binding[R] {

  def apply(): R = f(p1(),p2(),p3(),p4(),p5(),p6())

  def dependencies: Seq[Property[_]] = Seq(p1,p2,p3,p4,p5,p6)
}

/**
 * Implements [[jmmo.engine.property.Binding]] trait for 7 properties
 * form which depended some [[jmmo.engine.property.BoundProperty]]
 */
class Binding7[R, A,B,C,D,E,F,G](val f: (A,B,C,D,E,F,G) => R, val p1:Property[A],val p2:Property[B],val p3:Property[C],
                     val p4:Property[D],val p5:Property[E],val p6:Property[F],val p7:Property[G]) extends Binding[R] {

  def apply(): R = f(p1(),p2(),p3(),p4(),p5(),p6(),p7())

  def dependencies: Seq[Property[_]] = Seq(p1,p2,p3,p4,p5,p6,p7)
}

/**
 * Implements [[jmmo.engine.property.Binding]] trait for 8 properties
 * form which depended some [[jmmo.engine.property.BoundProperty]]
 */
class Binding8[R, A,B,C,D,E,F,G,H](val f: (A,B,C,D,E,F,G,H) => R, val p1:Property[A],val p2:Property[B],val p3:Property[C],
    val p4:Property[D],val p5:Property[E],val p6:Property[F],val p7:Property[G],val p8:Property[H]) extends Binding[R] {

  def apply(): R = f(p1(),p2(),p3(),p4(),p5(),p6(),p7(),p8())

  def dependencies: Seq[Property[_]] = Seq(p1,p2,p3,p4,p5,p6,p7,p8)
}

/**
 * Implements [[jmmo.engine.property.Binding]] trait for 9 properties
 * form which depended some [[jmmo.engine.property.BoundProperty]]
 */
class Binding9[R, A,B,C,D,E,F,G,H,I](val f: (A,B,C,D,E,F,G,H,I) => R, val p1:Property[A],val p2:Property[B],
                                        val p3:Property[C],val p4:Property[D],val p5:Property[E],val p6:Property[F],
                                        val p7:Property[G],val p8:Property[H],val p9:Property[I]) extends Binding[R] {

  def apply(): R = f(p1(),p2(),p3(),p4(),p5(),p6(),p7(),p8(),p9())

  def dependencies: Seq[Property[_]] = Seq(p1,p2,p3,p4,p5,p6,p7,p8,p9)
}
